package com.kymatrix.kycarbon.xsmd.common.util;

import com.kymatrix.kycarbon.xsmd.common.constants.Constant;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 日期工具类, 继承org.apache.commons.lang.time.DateUtils类
 */
@Slf4j
public class DateUtil extends org.apache.commons.lang3.time.DateUtils {

    public static final String YYYY_MM = "yyyy-MM";
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYYMMDD = "yyyyMMdd";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String HH_MM = "HH:mm";
    private static String[] parsePatterns = {YYYY_MM_DD, YYYY_MM_DD_HH_MM_SS, "yyyy-MM-dd HH:mm:ss.SSS",
        "yyyy-MM-dd HH:mm", YYYY_MM, "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.SSS",
        "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.SSS",
        "yyyy.MM.dd HH:mm", "yyyy.MM", "yyyyMMddHHmmss", YYYYMMDD, "yyyy-MM-dd'T'HH:mm:ss.SSS",
        "yyyy-MM-dd'T'HH:mm:ss:SSSZZ", "yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ss.SSS Z"};

    private static final String END_TIME = " 23:59:59";
    private static final String START_TIME = " 00:00:00";

    

    private DateUtil() {
        throw new IllegalStateException(Constant.FAILED);
    }

    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd）
     */
    public static String getDate() {
        return getDate(YYYY_MM_DD);
    }

    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String getDate(String pattern) {
        return DateFormatUtils.format(new Date(), pattern);
    }

    /**
     * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(Date date, Object... pattern) {
        String formatDate = null;
        if (pattern != null && pattern.length > 0) {
            formatDate = DateFormatUtils.format(date, pattern[0].toString());
        } else {
            formatDate = DateFormatUtils.format(date, YYYY_MM_DD);
        }
        return formatDate;
    }

    /**
     * formatDate
     */
    public static String formatDate(Date date) {
        return formatDate(date, YYYY_MM_DD);
    }

    /**
     * parseDate
     */
    public static Date parseDate(String date) {
        SimpleDateFormat df = new SimpleDateFormat(YYYY_MM_DD);
        try {
            return df.parse(date);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * parseDateTime
     */
    public static Date parseDateTime(String date) {
        SimpleDateFormat df = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        try {
            return df.parse(date);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String formatDateTime(Date date) {
        return formatDate(date, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String formatDateTime(Date date, String pattern) {
        return formatDate(date, pattern);
    }

    /**
     * 将传入的日期时间，转换格式 为pattern 格式的时间
     */
    public static Date formatDateToPattern(Date date, String pattern) {
        try {
            return parse(formatDate(date, pattern), pattern);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取 分钟是整5的时间
     */
    public static Date getNextMillisEndWithMinute0or5(Date baseTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(baseTime);
        int minute = calendar.get(Calendar.MINUTE);
        if (minute % 5 == 0) {
            return baseTime;
        } else {
            int add = 5 - minute % 5;
            calendar.add(Calendar.MINUTE, add);
        }
        return calendar.getTime();
    }


    /**
     * 得到当前时间字符串 格式（HH:mm:ss）
     */
    public static String getTime() {
        return formatDate(new Date(), "HH:mm:ss");
    }

    /**
     * 得到当前日期和时间字符串 格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String getDateTime() {
        return formatDate(new Date(), YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 得到当前年份字符串 格式（yyyy）
     */
    public static String getYear() {
        return formatDate(new Date(), "yyyy");
    }

    /**
     * 得到当前月份字符串 格式（MM）
     */
    public static String getMonth() {
        return formatDate(new Date(), "MM");
    }

    /**
     * 得到当天字符串 格式（dd）
     */
    public static String getDay() {
        return formatDate(new Date(), "dd");
    }

    /**
     * 得到当前星期字符串 格式（E）星期几
     */
    public static String getWeek() {
        return formatDate(new Date(), "E");
    }

    /**
     * 日期型字符串转化为日期 格式
     * {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
     * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM",
     * "yyyyMMddHHmmss","yyyyMMdd","yyyy-MM-dd'T'HH:mm:ss.SSS","yyyy-MM-dd'T'HH:mm:ss:SSSZZ",
     * "yyyy-MM-dd'T'HH:mm:ss.SSSX","yyyy-MM-dd'T'HH:mm:ss.SSS Z"}
     */
    public static Date parseDate(Object str) {
        if (str == null || "".equals(str)) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取过去的天数
     */
    public static long pastDays(Date date) {
        long time = System.currentTimeMillis() - date.getTime();
        return time / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取过去的小时
     */
    public static long pastHour(Date date) {
        long time = System.currentTimeMillis() - date.getTime();
        return time / (60 * 60 * 1000);
    }

    /**
     * 获取将来的小时
     */
    public static long futureHour(Date date) {
        long time = date.getTime() - System.currentTimeMillis();
        return time / (60 * 60 * 1000);
    }

    /**
     * 获取过去的分钟
     */
    public static long pastMinutes(Date date) {
        long time = System.currentTimeMillis() - date.getTime();
        return time / (60 * 1000);
    }

    /**
     * 转换为时间（天,时:分:秒.毫秒）
     */
    public static String formatDateTime(long timeMillis) {
        long day = timeMillis / (24 * 60 * 60 * 1000);
        long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
        long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long ss = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - ss * 1000);
        return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + ss + "." + sss;
    }

    /**
     * 获取两个日期之间的天数
     */
    public static double getDistanceOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000 * 60 * 60 * 24.0);
    }

    /**
     * 获取两个日期之间的分钟数
     */
    public static double getDistanceMinutesOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000 * 60.0);
    }

    /**
     * 获取两个日期之间的秒数
     */
    public static double getDistanceSecondsOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000.0);
    }

    /**
     * 获取两个日期之间的毫秒数
     */
    public static Long getDistanceMillisecondsOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return afterTime - beforeTime;
    }

    /**
     * 判断日期是否在两个日期之间
     * @param sourceDate 日期
     * @param startDate  开始日期
     * @param endDate    结束日期
     * @return 在返回true 不在返回false
     */
    public static boolean isBetween(Date sourceDate, Date startDate, Date endDate) {
        return ((sourceDate.compareTo(endDate) <= 0) && (startDate.compareTo(sourceDate) <= 0));
    }


    /**
     * 找出在某个范围之内的时间集合
     * @param start 开始
     * @param end 结束
     * @param list 源
     * @return teml 返回
     */
    public static List<Date> splitDate(Date start, Date end, List<Date> list) {
        List<Date> tem = new ArrayList<>();
        if (null != list && list.isEmpty()) {
            for (Date date : list) {
                if (date.getTime() == start.getTime() || date.getTime() == end.getTime()) {
                    tem.add(date);
                }
                if (date.after(start) && date.before(end)) {
                    tem.add(date);
                }
            }
        }
        return tem;

    }

    /**
     * 日期型字符串转化为日期 格式
     * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
     * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" }
     */
    public static Date parse(String strDate, String pattern) throws ParseException {
        return StringUtil.isBlank(strDate) ? null : new SimpleDateFormat(pattern).parse(strDate);
    }

    /**
     * 在日期上增加数个整月
     */
    public static Date addMonth(Date date, int num) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, num);
        return cal.getTime();
    }

    /**
     * 获取当前时间的后几天
     */
    public static Date getDateAfter(int addDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, addDay);
        return calendar.getTime();
    }

    /**
     * 获取当前时间的后几天返回值字符串
     */
    public static String getDateStrAfter(int addDay) {
        return formatDate(getDateAfter(addDay));
    }

    /**
     * 获取当前时间后几个月日期 返回date
     */
    public static Date getDateAfterMonth(int addMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, addMonth);
        return calendar.getTime();
    }

    /**
     * 获取当前时间后几个月日期 返回Str
     */
    public static String getDateStrAfterMonth(int addMonth) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDD);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, addMonth);
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取时间后几个月日期 返回date
     */
    public static Date getDateAfterMonthByDateStr(int addMonth, String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDD);
        Calendar calendar = Calendar.getInstance();
        Date now;
        try {
            now = sdf.parse(dateStr);
            calendar.setTime(now);
            calendar.add(Calendar.MONTH, addMonth);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return calendar.getTime();

    }

    /**
     * 获取时间后几个月日期 返回date
     */
    public static Date getDateAfterMonthByDate(int addMonth, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, addMonth);
        return calendar.getTime();
    }

    /**
     * 获取时间后几天 返回date
     */
    public static Date getDateAfterDayByDate(int addDay, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, addDay);
        return calendar.getTime();
    }

    /**
     * 获取过去第几天的日期
     */
    public static String getPastDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(YYYY_MM_DD);
        return format.format(today);
    }

    /**
     * 获取前几天的日期
     */
    public static String getLostPastDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(YYYY_MM_DD);
        return format.format(today);
    }

    /**
     * 获取时间后几个月日期 返回Str
     */
    public static String getDateAfterMonth(int addMonth, String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDD);
        Calendar calendar = Calendar.getInstance();
        Date now;
        try {
            now = sdf.parse(dateStr);
            calendar.setTime(now);
            calendar.add(Calendar.MONTH, addMonth);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取时间后几个月日期 返回str
     */
    public static String getDateAfterMonth(int addMonth, Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDD);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, addMonth);
        return sdf.format(calendar.getTime());
    }

    /**
     * 判断两个时间是不是在同一天
     */
    public static boolean isSameDate(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        boolean isSameYear = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
        boolean isSameMonth = isSameYear && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
        return isSameMonth && cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 判断两个时间是不是在同一个月
     */
    public static boolean isSameMonth(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        boolean isSameYear = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
        return isSameYear && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
    }

    /**
     * utc格式返回本地时间
     */
    public static String utc2local(String utcTimeStr, String pattern) {
        try {
            utcTimeStr = utcTimeStr.replace("Z", " UTC");// 注意是空格+UTC
            Date date = parseDate(utcTimeStr, parsePatterns);
            return formatDate(date, pattern);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * utc 转date
     */
    public static Date utc2Date(String utcTimeStr) {
        if (org.apache.commons.lang3.StringUtils.isBlank(utcTimeStr)) {
            return new Date();
        }
        Instant instant = Instant.parse(utcTimeStr);
        try {
            return new Date(instant.toEpochMilli());
        } catch (ArithmeticException ex) {
            throw new IllegalArgumentException(ex);
        }
    }



    /**
     * 判断日期大小
     */
    public static Boolean compareDate(String beginTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        return sdf.parse(beginTime).getTime() <= sdf.parse(endTime).getTime();
    }

    /**
     * 得到某年某周的第一天
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);

        Calendar cal = (Calendar) calendar.clone();
        cal.add(Calendar.DATE, week * 7);

        return getFirstDayOfWeek(cal.getTime());
    }

    /**
     * 得到某年某周的最后一天
     */
    public static Date getLastDayOfWeek(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);
        Calendar cal = (Calendar) calendar.clone();
        cal.add(Calendar.DATE, week * 7);

        return getLastDayOfWeek(cal.getTime());
    }

    /**
     * String转为Date
     */
    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD);
        return formatter.parse(strDate, new ParsePosition(0));
    }

    /**
     * 取得当前日期所在周的第一天
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); // Monday
        return calendar.getTime();
    }

    /**
     * 取得当前日期所在周的最后一天
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek() + 6); // Sunday
        return calendar.getTime();
    }


    /**
     * 取得当前日期所在周的前一周最后一天
     */
    public static Date getLastDayOfLastWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        return getLastDayOfWeek(calendar.get(Calendar.YEAR), calendar.get(Calendar.WEEK_OF_YEAR) - 1);
    }

    /**
     * 取得当前日期所在周的前一周第一天
     */
    public static Date getFirstDayOfLastWeek(Date date) {
        return getFirstDayOfWeek(getLastDayOfLastWeek(date));
    }

    /**
     * 返回指定日期的月的第一天
     */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1);
        return calendar.getTime();
    }

    /**
     * 返回指定年月的月的第一天
     */
    public static Date getFirstDayOfMonth(Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        if (year == null) {
            year = calendar.get(Calendar.YEAR);
        }
        if (month == null) {
            month = calendar.get(Calendar.MONTH);
        }
        calendar.set(year, month, 1);
        return calendar.getTime();
    }

    /**
     * 获取本月最后一天
     */
    public static Date getLastDayMonth(String time) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, StringUtil.toInteger(time.substring(0, 4)));
        cal.set(Calendar.MONTH, StringUtil.toInteger(time.substring(5, 7)) - 1);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 获取本月最后一天
     */
    public static String getLastDayStringMonth(String time) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, StringUtil.toInteger(time.substring(0, 4)));
        cal.set(Calendar.MONTH, StringUtil.toInteger(time.substring(5, 7)));
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.DATE, -1);
        SimpleDateFormat sd = new SimpleDateFormat(YYYY_MM_DD);
        return sd.format(cal.getTime());
    }


    /**
     * 获取本月第一天
     */
    public static Date getMonthFirstDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.MONTH, 0);
        return calendar.getTime();
    }

    /**
     * 获取本季度第一天
     */
    public static Date getFirstDayQuarter() {
        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH) + 1;
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        String firstDayOfCurrentQuarter = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 3) {
                calendar.set(Calendar.MONTH, 0);
            } else if (currentMonth >= 4 && currentMonth <= 6) {
                calendar.set(Calendar.MONTH, 3);
            } else if (currentMonth >= 7 && currentMonth <= 9) {
                calendar.set(Calendar.MONTH, 4);
            } else if (currentMonth >= 10 && currentMonth <= 12) {
                calendar.set(Calendar.MONTH, 9);
            }
            calendar.set(Calendar.DATE, 1);
            firstDayOfCurrentQuarter = sdf.format(calendar.getTime());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        Date parsea = null;
        try {
            parsea = sdf.parse(firstDayOfCurrentQuarter);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return parsea;
    }

    /**
     * 获取本季度最后一天
     */
    public static Date getLastDayQuarter() {

        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH) + 1;
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        String lastDayOfCurrentQuarter = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 3) {
                calendar.set(Calendar.MONTH, 2);
                calendar.set(Calendar.DATE, 31);
            } else if (currentMonth >= 4 && currentMonth <= 6) {
                calendar.set(Calendar.MONTH, 5);
                calendar.set(Calendar.DATE, 30);
            } else if (currentMonth >= 7 && currentMonth <= 9) {
                calendar.set(Calendar.MONTH, 8);
                calendar.set(Calendar.DATE, 30);
            } else if (currentMonth >= 10 && currentMonth <= 12) {
                calendar.set(Calendar.MONTH, 11);
                calendar.set(Calendar.DATE, 31);
            }
            lastDayOfCurrentQuarter = sdf.format(calendar.getTime());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        Date parsea = null;
        try {
            parsea = sdf.parse(lastDayOfCurrentQuarter);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return parsea;
    }

    /**
     * 获取当前时间所属季度结束月最后一天
     */
    public static String quarterEnd(String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        Date end = null;
        try {
            end = sdf.parse(endDate);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(end);
        int remainder = (calendar.get(Calendar.MONTH) + 1) % 3;
        int month = remainder != 0 ? calendar.get(Calendar.MONTH) + (3 - remainder) : calendar.get(Calendar.MONTH);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.setTime(calendar.getTime());
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取当前天数的后几天
     */
    public static Date getSpecifiedDayAfter(String str, Integer day) throws ParseException {
        Calendar cal = Calendar.getInstance();
        cal.setTime(parse(str, YYYY_MM_DD));
        cal.set(Calendar.DATE, cal.get(Calendar.DATE) + day);
        return cal.getTime();
    }

    /**
     * 获取昨天日期
     */
    public static String getYesterday() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        SimpleDateFormat sp = new SimpleDateFormat(YYYY_MM_DD);
        return sp.format(cal.getTime());
    }

    /**
     * 返回指定日期的月的最后一天
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定年月的下个月的最后一天
     */
    public static Date getLastDayOfMonth(Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        if (year == null) {
            year = calendar.get(Calendar.YEAR);
        }
        if (month == null) {
            month = calendar.get(Calendar.MONTH);
        }
        calendar.set(year, month, 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定日期的上个月的最后一天
     */
    public static Date getLastDayOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - 1, 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定日期的季的第一天
     */
    public static Date getFirstDayOfQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getFirstDayOfQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的季的第一天
     */
    public static Date getFirstDayOfQuarter(Integer year, Integer quarter) {
        Calendar calendar = Calendar.getInstance();
        Integer month;
        if (quarter == 1) {
            month = 0;
        } else if (quarter == 2) {
            month = 4 - 1;
        } else if (quarter == 3) {
            month = 7 - 1;
        } else if (quarter == 4) {
            month = 10 - 1;
        } else {
            month = calendar.get(Calendar.MONTH);
        }
        return getFirstDayOfMonth(year, month);
    }

    /**
     * 返回指定日期的季的最后一天
     */
    public static Date getLastDayOfQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getLastDayOfQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的季的最后一天
     */
    public static Date getLastDayOfQuarter(Integer year, Integer quarter) {
        Calendar calendar = Calendar.getInstance();
        Integer month;
        if (quarter == 1) {
            month = 3 - 1;
        } else if (quarter == 2) {
            month = 6 - 1;
        } else if (quarter == 3) {
            month = 9 - 1;
        } else if (quarter == 4) {
            month = 12 - 1;
        } else {
            month = calendar.get(Calendar.MONTH);
        }
        return getLastDayOfMonth(year, month);
    }

    /**
     * 返回指定日期的上一季的最后一天
     */
    public static Date getLastDayOfLastQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getLastDayOfLastQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的上一季的最后一天
     */
    public static Date getLastDayOfLastQuarter(Integer year, Integer quarter) {
        Calendar calendar = Calendar.getInstance();
        Integer month;
        if (quarter == 1) {
            month = 12 - 1;
        } else if (quarter == 2) {
            month = 3 - 1;
        } else if (quarter == 3) {
            month = 6 - 1;
        } else if (quarter == 4) {
            month = 9 - 1;
        } else {
            month = calendar.get(Calendar.MONTH);
        }
        return getLastDayOfMonth(year, month);
    }

    /**
     * 返回指定日期的季度
     */
    public static int getQuarterOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) / 3 + 1;
    }

    /**
     * 将时间转化成yyyy-MM-dd 23:59:59格式
     */
    public static Date forDateAddDay(Date packageEndDate) throws ParseException {
        String newDate = formatDate(packageEndDate, YYYY_MM_DD);
        newDate = newDate + END_TIME;
        return parse(newDate, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取一天开始的时间
     */
    public static Date getDayStart(Date date) throws ParseException {
        String newDate = formatDate(date, YYYY_MM_DD);
        newDate = newDate + START_TIME;
        return parse(newDate, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取一天结束的时间
     */
    public static Date getDayEnd(Date date) throws ParseException {
        String newDate = formatDate(date, YYYY_MM_DD);
        newDate = newDate + END_TIME;
        return parse(newDate, YYYY_MM_DD_HH_MM_SS);
    }


    /**
     * 获取某年某月有多少天
     *
     * @param year  例 ： 2018
     * @param month 例 ：7
     * @return 天数
     */
    public static int getDayNumOfMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, 0); // 输入类型为int类型
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param dt 日期
     * @return 当前日期是星期几
     */
    public static String getWeekOfDate(Date dt, String... weekFormats) {
        if (weekFormats != null) {
            if (7 != weekFormats.length) {
                throw new ArrayIndexOutOfBoundsException("数组数量小于 7 或者 大于 7 ");
            }
        } else {
            weekFormats = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);

        int res = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (res < 0) {
            res = 0;
        }
        return weekFormats[res];
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param dateStr 日期字符串
     * @return 当前日期是星期几
     */
    public static String getWeekOfDate(String dateStr, String... weekFormats) {
        Date date = DateUtil.parseDate(dateStr);
        return getWeekOfDate(date, weekFormats);
    }

    /**
     * 根据Date获取cron表达式
     *
     * @param date 日期
     * @return cron表达式
     */
    public static String getCron(Date date) {
        String dateFormat = "ss mm HH dd MM ?";
        return formatDate(date, dateFormat);
    }

    /**
     * 两个日期相差月份
     */
    public static int getMonthSpace(String date1, String date2, boolean isAbs) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        return getMonthSpace(sdf.parse(date1), sdf.parse(date2), isAbs);
    }

    /**
     * 两个日期相差月份
     */
    public static int getMonthSpace(Date date1, Date date2, boolean isAbs) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(date1);
        c2.setTime(date2);
        int result = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
        return isAbs ? Math.abs(result) : result;
    }

    /**
     * 判断当前日期是星期几
     * @param time 要判断的时间
     * @return dayForWeek 判断结果
     */
    public static int dayForWeek(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int dayForWeek = 0;
        if (calendar.get(Calendar.DAY_OF_WEEK) == 1) {
            dayForWeek = 7;
        } else {
            dayForWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }

    /**
     * 判断传入日期是星期几
     *
     * @param time 要判断的时间
     * @return dayForWeek 判断结果
     */
    public static int dayForWeek(String time) {
        return dayForWeek(DateUtil.parseDate(time));
    }

    /**
     * 判断日期为第几周<br>
     * 注：日期为星期天时要注意(周天~周六为一周)
     *
     * @param time 时间
     * @return 周
     */
    public static int getWhichWeek(String time) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(parse(time, YYYY_MM_DD));
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 将秒 转为时分秒格式
     */
    public static String formatSecond(String str) {
        Long seconds = Long.parseLong(str);
        Long temp;
        StringBuilder sb = new StringBuilder();
        temp = seconds / 3600;
        sb.append((temp < 10) ? "0" + temp + ":" : "" + temp + ":");

        temp = seconds % 3600 / 60;
        sb.append((temp < 10) ? "0" + temp + ":" : "" + temp + ":");

        temp = seconds % 3600 % 60;
        sb.append((temp < 10) ? "0" + temp : "" + temp);
        return sb.toString();
    }

    /**
     * 获取指定日期的前一天
     */
    public static String getBeforeDay(String specifiedDay) {
        Calendar calendar = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat(YYYY_MM_DD).parse(specifiedDay);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.DATE, day - 1);

        return new SimpleDateFormat(YYYY_MM_DD).format(calendar.getTime());
    }

    /**
     * 获取指定日期的前一天
     */
    public static String getBeforeDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.DATE, day - 1);
        return new SimpleDateFormat(YYYY_MM_DD).format(calendar.getTime());
    }

    /**
     * 获取startDate日期后month月的日期
     *
     * @param startDate 开始日期
     * @param month     几个月后
     * @return 日期
     */
    public static Date getMonthDate(Date startDate, int month) {

        LocalDateTime localDateTime = startDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime().plusMonths(month);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取日期时间段内的每一天
     */
    public static List<String> findDates(String begin, String end) throws ParseException {
        //日期工具类准备
        DateFormat format = new SimpleDateFormat(YYYY_MM_DD);

        //设置开始时间
        Calendar calBegin = Calendar.getInstance();
        calBegin.setTime(format.parse(begin));

        //设置结束时间
        Calendar calEnd = Calendar.getInstance();
        calEnd.setTime(format.parse(end));

        //装返回的日期集合容器
        List<String> dateList = new ArrayList<>();

        // 每次循环给calBegin日期加一天，直到calBegin.getTime()时间等于dEnd
        dateList.add(begin);
        while (format.parse(end).after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            dateList.add(format.format(calBegin.getTime()));
        }
        return dateList;
    }

    /**
     * 根据当前日期以及指定天数，获取指定天数之前的日期
     */
    public static String getDaysBeforeDate(int days, String times) throws ParseException {
        Date endDate = DateUtil.parseDate(times, YYYY_MM_DD);
        DateFormat df = new SimpleDateFormat(YYYY_MM_DD);
        long time = endDate.getTime() - days * 24 * 60 * 60 * 1000;
        Date date = new Date(time);
        return df.format(date);

    }

    /**
     * 获取两个时间的差值yyyy-MM-dd HH:mm:ss 两个字符串类型 返回天
     */
    public static double getTwoTimeDifference(String small, String big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        Date sm = formatter.parse(small, new ParsePosition(0));
        Date date = formatter.parse(big, new ParsePosition(0));
        BigDecimal time = new BigDecimal(date.getTime() - sm.getTime());
        BigDecimal divide = time.divide(new BigDecimal(3600000 * 24), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }

    /**
     * 获取两个时间的差值yyyy-MM-dd 两个字符串类型 返回小时
     */
    public static double getTwoTimeDifferenceByDay(String small, String big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD);
        Date sm = formatter.parse(small, new ParsePosition(0));
        Date date = formatter.parse(big, new ParsePosition(0));
        BigDecimal time = new BigDecimal(date.getTime() - sm.getTime());
        BigDecimal divide = time.divide(new BigDecimal(3600000), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }

    /**
     * 获取两个时间的差值 两个字符串类型yyyy-MM-dd HH:mm:ss   返回小时
     */
    public static double getTwoTimeDifferenceHours(String small, String big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        Date sm = formatter.parse(small, new ParsePosition(0));
        Date date = formatter.parse(big, new ParsePosition(0));
        BigDecimal time = new BigDecimal(date.getTime() - sm.getTime());
        BigDecimal divide = time.divide(new BigDecimal(3600000), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }

    /**
     * 获取两个时间的差值 两个字符串类型yyyy-MM-dd HH:mm:ss  返回小时
     */
    public static double getTwoTimeDifferenceHours(String small, Date big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        Date sm = formatter.parse(small, new ParsePosition(0));
        BigDecimal bigDecimal = new BigDecimal(big.getTime() - sm.getTime());
        BigDecimal divide = bigDecimal.divide(new BigDecimal(3600000), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }


    /**
     * 获取两个时间的差值yyyy-MM-dd HH:mm:ss 一个字符串一个时间类型 返回天
     */
    public static double getTwoTimeDifference(String small, Date big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        Date sm = formatter.parse(small, new ParsePosition(0));
        BigDecimal bigDecimal = new BigDecimal(big.getTime() - sm.getTime());
        BigDecimal divide = bigDecimal.divide(new BigDecimal(3600000 * 24), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }


    /**
     * 获取两个时间相差天数
     */
    public static double getTwoTimeBad(String small, String big) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD);
        Date sm = formatter.parse(small, new ParsePosition(0));
        Date date = formatter.parse(big, new ParsePosition(0));
        BigDecimal time = new BigDecimal(date.getTime() - sm.getTime());
        BigDecimal divide = time.divide(new BigDecimal(3600000 * 24), 2, RoundingMode.HALF_UP);
        if (divide.doubleValue() < 0) {
            return divide.multiply(new BigDecimal(-1)).doubleValue();
        }
        return divide.doubleValue();
    }

    /**
     * 获取前/后半年的开始时间
     */
    public static Date getHalfYearStartTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        SimpleDateFormat shortSdf = new SimpleDateFormat(YYYY_MM_DD);
        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH) + 1;
        Date now = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 6) {
                calendar.set(Calendar.MONTH, 0);
            } else if (currentMonth >= 7 && currentMonth <= 12) {
                calendar.set(Calendar.MONTH, 6);
            }
            calendar.set(Calendar.DATE, 1);
            now = formatter.parse(shortSdf.format(calendar.getTime()) + START_TIME);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return now;

    }

    /**
     * 获取前/后半年的结束时间
     */
    public static Date getHalfYearEndTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        SimpleDateFormat shortSdf = new SimpleDateFormat(YYYY_MM_DD);
        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH) + 1;
        Date now = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 6) {
                calendar.set(Calendar.MONTH, 5);
                calendar.set(Calendar.DATE, 30);
            } else if (currentMonth >= 7 && currentMonth <= 12) {
                calendar.set(Calendar.MONTH, 11);
                calendar.set(Calendar.DATE, 31);
            }
            now = formatter.parse(shortSdf.format(calendar.getTime()) + END_TIME);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return now;
    }

    /**
     * 当前年的开始时间，即2012-01-01 00:00:00
     */
    public static Date getCurrentYearStartTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD);
        Calendar calendar = Calendar.getInstance();
        Date now = null;
        try {
            calendar.set(Calendar.MONTH, 0);
            calendar.set(Calendar.DATE, 1);
            now = formatter.parse(formatter.format(calendar.getTime()) + START_TIME);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return now;
    }

    /**
     * 当前年的结束时间，即2012-12-31 23:59:59
     */
    public static Date getCurrentYearEndTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        Calendar calendar = Calendar.getInstance();
        Date now = null;
        try {
            calendar.set(Calendar.MONTH, 11);
            calendar.set(Calendar.DATE, 31);
            now = formatter.parse(formatter.format(calendar.getTime()) + END_TIME);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return now;
    }


    /**
     * get16UUID
     */
    public static Long get16Uuid() {
        // 1.开头两位，标识业务代码或机器代码（可变参数）
        String machineId = "41";
        // 2.中间四位整数，标识日期
        SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
        String dayTime = sdf.format(new Date());
        // 3.生成uuid的hashCode值
        int hashCode = UUID.randomUUID().toString().hashCode();
        // 4.可能为负数
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        // 5.算法处理: 0-代表前面补充0; 10-代表长度为10; d-代表参数为正数型
        String value = machineId + dayTime + String.format("%010d", hashCode);
        return Long.valueOf(value);
    }

    /**
     * 获取时间戳
     */
    public static Long datetimeToTimeStamp(LocalDateTime localDateTime) {
        if (localDateTime != null) {
            return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        } else {
            return null;
        }

    }

    /**
     * 将 LocalDateTime 转换成 Date
     *
     * @param date LocalDateTime
     * @return LocalDateTime
     */
    public static Date of(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        // 将此日期时间与时区相结合以创建 ZonedDateTime
        ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
        // 本地时间线 LocalDateTime 到即时时间线 Instant 时间戳
        Instant instant = zonedDateTime.toInstant();
        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
        return Date.from(instant);
    }

    /**
     * 将 Date 转换成 LocalDateTime
     *
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime of(Date date) {
        if (date == null) {
            return null;
        }
        // 转为时间戳
        Instant instant = date.toInstant();
        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
}
